#include "StdAfx.h"
#include "SkinableGUIImage.h"

#include "SkinManager.h"
#include "pathutils.h"

#include "ximage.h"

#include <memory>

using namespace SkinableGUI;

CSkinableGUIImage::CSkinableGUIImage(void) :
m_pImageData(NULL)
{
}

CSkinableGUIImage::~CSkinableGUIImage(void)
{
	Release();
}

void CSkinableGUIImage::Release()
{
	if (NULL != m_pImageData)
	{
		CxImage ** ppImages = (CxImage **)m_pImageData;

		for(int i = 0; i < m_nFrames; i++)
		{
			delete ppImages[i];
		}

		delete m_pImageData;
	}

	m_pImageData = NULL;
}

BOOL CSkinableGUIImage::Load(const CString & path, BOOL bTransparent,
			COLORREF transparentColor)
{
	if (path.GetLength() == 0)
		return TRUE;

	CSkinManager * pManager = CSkinManager::GetInstance();

	CString imagesPath = pManager->GetMediaPath();

	if (PathUtils::IsPathRooted(path))
	{
		imagesPath = path;
	}
	else
	{
		imagesPath.AppendFormat(_T("\\%s"), path);
	}

#ifdef _WIN32_WCE
	FILE * fp = _tfopen(imagesPath, _T("rb"));

	fseek(fp, 0, SEEK_END);
	long length = ftell(fp);
	fseek(fp, 0, SEEK_SET);

	std::auto_ptr<unsigned char> buf(new unsigned char[length]);

	fread(buf.get(), sizeof(unsigned char), length, fp);

	fclose(fp);

	return LoadBuffer(buf.get(),
		length, bTransparent, transparentColor);
#else
	std::auto_ptr<CxImage> image(new CxImage());
	image->SetRetreiveAllFrames(true);

	if (image->Load(imagesPath))
	{
		m_bTransparent = bTransparent;
		m_TransparentColor = transparentColor;

		HandleImagesFrame(image.get(), imagesPath);

		return TRUE;
	}

	return FALSE;
#endif
}

void CSkinableGUIImage::HandleImagesFrame(void * p, 
										  const CString & path, 
										  unsigned char * buffer,
										  int buffer_size)
{
	CxImage * pImage = (CxImage *)p;

	m_nFrames = pImage->GetNumFrames();

	if (m_nFrames == 0) m_nFrames = 1;

	CxImage ** ppImages = new CxImage *[m_nFrames];

	if (m_pImageData != NULL)
		Release();

	m_pImageData = (void *)ppImages;

	for(int i=0;i<m_nFrames;i++)
	{
		ppImages[i] = new CxImage();
		ppImages[i]->SetFrame(i);

		if (buffer == NULL)
			ppImages[i]->Load(path);
		else
			ppImages[i]->Decode(buffer, buffer_size, CXIMAGE_FORMAT_UNKNOWN);
	}
}

void CSkinableGUIImage::BltFrame(int nFrame, CDC * pDC, LPRECT pRect, LPRECT pClipRect)
{
	if (nFrame >= m_nFrames || nFrame < 0)
		return;

	CRect rc = m_DefaultRect;
	
	if (NULL != pRect)
		rc = *pRect;

	if (NULL == m_pImageData)
		return;

	CxImage ** ppImages = (CxImage **)m_pImageData;

	CxImage * pImage = ppImages[nFrame];

	pImage->Draw(pDC->GetSafeHdc(), rc, pClipRect, FALSE);
}

void CSkinableGUIImage::Blt(CDC * pDC, LPRECT pRect, LPRECT pClipRect)
{
	BltFrame(0, pDC, pRect, pClipRect);
}

BOOL CSkinableGUIImage::Load(SkinImage * pSkinImage)
{
	return Load(pSkinImage->Path, pSkinImage->Transparent,
		pSkinImage->TransparentColor.ToColor());
}

BOOL CSkinableGUIImage::LoadBuffer(unsigned char * buf, int buf_size, BOOL bTransparent,
			COLORREF transparentColor)
{
	std::auto_ptr<CxImage> image(new CxImage());
	image->SetRetreiveAllFrames(true);

	if (image->Decode(buf, buf_size, CXIMAGE_FORMAT_UNKNOWN))
	{
		m_bTransparent = bTransparent;
		m_TransparentColor = transparentColor;

		HandleImagesFrame(image.get(), _T(""), buf, buf_size);

		return TRUE;
	}

	return FALSE;
}

CSize CSkinableGUIImage::GetImageSize() const
{
	if (NULL == m_pImageData)
		return CSize(0,0);

	CxImage ** ppImages = (CxImage **)m_pImageData;

	CxImage * pImage = ppImages[0];

	return CSize(pImage->GetWidth(),
		pImage->GetHeight());
}
